<template>
  <a-form class="form" :model="Data">
    <template v-for="(module, index) in Data" :key="index">
      <a-form-item class="itemTitle">
        <div class="title">{{ numberToChinese(index + 1) + '、' + module.name }}</div>
      </a-form-item>
      <template v-for="(subitem, i) in module.list" :key="i">
        <visible-render height="50px" style="margin-bottom: 16px">
          <form-item
            v-model:subitem="module.list[i]"
            :i="i"
            :disabled="disabled"
            @change="formDataFilter"
          />
        </visible-render>
        <template v-if="$slots.custom">
          <div>
            <slot name="custom" :item="subitem" :index="[index, i]" />
          </div>
        </template>
      </template>
    </template>
  </a-form>
</template>

<script setup lang="ts">
import { watch, ref, nextTick } from 'vue'
import VisibleRender from '@/components/VisibleRender/index.vue'
import FormItem from './formItem.vue'
import { numberToChinese, typeOf } from '@/utils/tools'

const Data = ref([])

const transform = (obj) => {
  if (typeOf(obj.value) === 'string') {
    return new Function('x', 'return x ' + obj.operator + ' "' + obj.value + '"')
  } else {
    return new Function('x', 'return x ' + obj.operator + ' ' + obj.value)
  }
}

const transformCustom = (str, obj) => {
  const s = str.replace(/\$\{(.*?)\}/g, (_, key) => {
    if (Object.prototype.hasOwnProperty.call(obj, key)) {
      return obj[key].value
    } else {
      throw new Error('自定义条件执行异常找不到变量')
    }
  })
  const f = new Function('x', 'return ' + s)
  console.log(f())
  return f()
}

const loop = (obj, d) => {
  if (obj.operator === 'AND') {
    return obj.conditions.every((v) => {
      if (v.operator !== 'AND' && v.operator !== 'OR') {
        if (v.operator === '填写完成') {
          return d[v.id].value.trim() !== ''
        } else {
          if (v.id === 'custom') {
            return transformCustom(v.value, d)
          } else if (d[v.id].type.includes('单选')) {
            return d[v.id].sort == v.value
          } else if (d[v.id].type.includes('多选')) {
            return d[v.id].sort.includes(v.value)
          } else if (d[v.id].type === '数字选择') {
            const f = transform(v)
            console.log(d[v.id].value)
            return f(d[v.id].value)
          } else if (d[v.id].type === '输入') {
            const f = transform(v)
            return f(d[v.id].value)
          }
          if (typeOf(d[v.id].value) === 'string') {
            return d[v.id].value.trim() !== ''
          } else if (typeOf(d[v.id].value) === 'array') {
            return d[v.id].value.length > 0
          } else {
            return true
          }
          // return f(d[v.id].value)
        }
      } else {
        return loop(v, d)
      }
    })
  } else if (obj.operator === 'OR') {
    return obj.conditions.some((v) => {
      if (v.operator !== 'AND' && v.operator !== 'OR') {
        if (v.operator === '填写完成') {
          return d[v.id].value.trim() !== ''
        } else {
          if (v.id === 'custom') {
            return transformCustom(v.value, d)
          } else if (d[v.id].type.includes('单选')) {
            return d[v.id].sort == v.value
          } else if (d[v.id].type.includes('多选')) {
            return d[v.id].sort.includes(v.value)
          } else if (d[v.id].type === '数字选择') {
            const f = transform(v)
            return f(d[v.id].value)
          } else if (d[v.id].type === '输入') {
            const f = transform(v)
            return f(d[v.id].value)
          }
          if (typeOf(d[v.id].value) === 'string') {
            return d[v.id].value.trim() !== ''
          } else if (typeOf(d[v.id].value) === 'array') {
            return d[v.id].value.length > 0
          } else {
            return true
          }
          // return f(d[v.id].value)
        }
      } else {
        return loop(v, d)
      }
    })
  }
  return true
}

const showCondition = (arr) => {
  const obj = {}
  arr.map((v) => {
    v.list.map((u) => {
      obj[u.id] = u
    })
  })

  const List = []

  for (const v of arr) {
    const L = v.list.filter((u) => {
      if (!u.showCondition) {
        return true
      }
      let show = true
      if (Object.prototype.hasOwnProperty.call(u.showCondition, 'show')) {
        show = u.showCondition.show
      }
      let r
      try {
        r = loop(u.showCondition, obj)
      } catch (e) {
        throw new Error(`自定义条件执行异常，异常问题：${u.name}`)
      }
      if (show) {
        return r
      } else {
        return !r
      }
    })
    if (L.length) {
      List.push({
        ...v,
        list: L
      })
    }
  }

  return List
}

const formDataFilter = () => {
  console.time('1')
  if (props.condition) {
    Data.value = showCondition(props.formData)
  } else {
    Data.value = props.formData
  }
  console.timeEnd('1')
}

const props = defineProps({
  formData: {
    default: []
  },
  disabled: {
    default: false
  },
  condition: {
    default: false
  }
})
const emit = defineEmits(['update:formData', 'reset'])

watch(
  () => props?.formData,
  () => {
    Data.value = []
    nextTick(() => {
      formDataFilter()
    })
  },
  {
    immediate: true
  }
)
</script>

<style lang="less" scope>
.ant-form-item {
  &.itemTitle {
    margin-bottom: 5px;

    .title {
      height: 32px;
      padding-left: 16px;
      font-family: 'PingFang SC';
      font-size: 14px;
      font-weight: 600;
      line-height: 32px;
    }
  }

  &.subitemName {
    margin-bottom: 0;
  }

  &.subitemNameCheckbox {
    margin-bottom: 0;
  }

  .textarea {
    width: 50%;
    padding-right: 16px;
    padding-left: 16px;
  }
}

html[theme='light'] {
  .ant-form-item {
    font-size: 14px;

    &.itemTitle {
      background: #f7f8fa;

      .title {
        color: #1d2129;
      }
    }
  }
}

.red {
  color: #ff1313;
}

.form {
  .ant-radio-wrapper-disabled,
  .ant-input-disabled,
  .ant-input[disabled],
  .ant-checkbox-disabled + span {
    color: #1d2129;
  }

  .ant-radio-wrapper .ant-radio-disabled .ant-radio-inner::after {
    color: #1d2129;
  }

  .ant-checkbox-checked.ant-checkbox-disabled .ant-checkbox-inner {
    background: #94bfff;
  }

  .ant-checkbox-disabled .ant-checkbox-inner::after {
    border-color: #fff;
  }

  .ant-radio-wrapper .ant-radio-checked.ant-radio-disabled .ant-radio-inner {
    background: #94bfff;
  }

  .ant-radio-wrapper .ant-radio-disabled.ant-radio-checked .ant-radio-inner::after {
    background-color: #fff;
  }

  .ant-picker .ant-picker-input > input-disabled,
  .ant-picker .ant-picker-input > input[disabled] {
    color: #1d2129;
  }
}
</style>
